package com.bosch.in.rtp1.ept.manager.impl;

import java.sql.SQLException;
import java.util.List;

import org.apache.log4j.Logger;

import com.bosch.in.rtp1.ept.constant.CommonConstants;
import com.bosch.in.rtp1.ept.constant.HoldCodeType;
import com.bosch.in.rtp1.ept.dao.HoldCodeFilterDao;
import com.bosch.in.rtp1.ept.manager.HoldCodeFilterManager;
import com.bosch.in.rtp1.ept.model.dto.HoldCodeFilter;
import com.bosch.in.rtp1.ept.util.DaoFactory;
import com.bosch.in.rtp1.ept.util.HoldCodeUtility;
import com.bosch.in.rtp1.ept.util.ehcache.EhcacheFactory;

/**
 * Concrete implementation of HoldCodeFilterManager which provides service to manipulate 
 * LotStatus data, delegate data source retrieval and transaction management to 
 * DBConnectionManager attribute.  
 * @author TPR1HC
 *
 */
public class HoldCodeFilterManagerImpl implements HoldCodeFilterManager{
	/**
	 * used to manage connection
	 */
	private DBConnectionManager dbManager;
	/**
	 * DAO object to get HoldCode filter data.
	 */
	private HoldCodeFilterDao holdCodeFilterDao;
	
	private static final Logger LOGGER = Logger.getLogger(HoldCodeFilterManagerImpl.class);
	
	/**
	 * Look up datasource to get connection from pre-initialized connection pool
	 */
	public HoldCodeFilterManagerImpl() { 
		
	}

	/**
	 * lazy initialize connection when we really need to interact with database and in case 
	 * data can't be found in caching system.
	 * @throws SQLException
	 */
	private void init() throws SQLException {
		dbManager = new DBConnectionManager();
		holdCodeFilterDao = DaoFactory.getInstance().getHoldCodeFilterDao(dbManager.getConnection());
	}

	@Override
	public List<HoldCodeFilter> getHoldCodeFilters(HoldCodeType hcType) throws SQLException {
		LOGGER.debug("Begin HoldCodeFilterManagerImpl.getHoldCodeFilters");
		try {
			List<HoldCodeFilter> hcFilters = getAllHoldCodeFilters();
			return HoldCodeUtility.extractHoldCode(hcFilters, hcType);
		} finally {
			LOGGER.debug("End HoldCodeFilterManagerImpl.getHoldCodeFilters");
		}
	}

	@Override
	public boolean updateHoldCodeFilter(List<HoldCodeFilter> hcFilters) throws SQLException
			 {
		LOGGER.debug("Begin HoldCodeFilterManagerImpl.updateHoldCodeFilter");
		try {
			// lazy init connection
			init();
			invalidateCaches();
			
			return holdCodeFilterDao.updateHoldCodeFilter(hcFilters);
		} finally {
			dbManager.commit();
			LOGGER.debug("Commited updateHoldCodeFilter");
			dbManager.close();
			LOGGER.debug("Closed connection");
			LOGGER.debug("End HoldCodeFilterManagerImpl.updateHoldCodeFilter");
		}
	}

	@Override
	public int insertHoldCodeFilter(HoldCodeFilter hcFilter) throws SQLException {
		LOGGER.debug("Begin HoldCodeFilterManagerImpl.insertHoldCodeFilter");
		try {
			
			// find if we are updating HoldCodeGrouping
			boolean hcGrouping = false; 
			if (hcFilter.getType() == HoldCodeType.HC_RECLASF) {
				hcGrouping = true;
			}
			
			// lazy init connection
			init();
			invalidateCaches();
			
			if (hcGrouping) {
				// new HoldCode will be inserted to the second last order.
				hcFilter.setOrder(holdCodeFilterDao.getLastOrderOfHoldCodeFilter(hcFilter.getType()));
				
				// move REST to last position
				HoldCodeFilter rest = new HoldCodeFilter();
				rest.setComment(HoldCodeUtility.REST);
				rest.setType(HoldCodeType.HC_RECLASF);
				rest.setOrder(hcFilter.getOrder() + 1);
				holdCodeFilterDao.setLastPosition(rest);
				
			} else {
				// new HoldCode will be inserted to the last order.
				hcFilter.setOrder(holdCodeFilterDao.getLastOrderOfHoldCodeFilter(hcFilter.getType()) + 1);
			}
			
			return holdCodeFilterDao.insertHoldCodeFilter(hcFilter);
		} finally {
			dbManager.commit();
			LOGGER.debug("Commited insertHoldCodeFilter");
			dbManager.close();
			LOGGER.debug("Closed connection");
			LOGGER.debug("End HoldCodeFilterManagerImpl.insertHoldCodeFilter");
		}
	}

	@Override
	public boolean deleteHoldCodeFilter(int id) throws SQLException {
		LOGGER.debug("Begin HoldCodeFilterManagerImpl.deleteHoldCodeFilter");
		try {
			// lazy init connection
			init();
			
			invalidateCaches();
			
			return holdCodeFilterDao.deleteHoldCodeFilter(id);
		} finally {
			dbManager.commit();
			LOGGER.debug("Commited deleteHoldCodeFilter");
			dbManager.close();
			LOGGER.debug("Closed connection");
			LOGGER.debug("End HoldCodeFilterManagerImpl.deleteHoldCodeFilter");
		}
	}

	@Override
	public boolean reorderHoldCodeFilters(List<Integer> idList) throws SQLException
			{
		LOGGER.debug("Begin HoldCodeFilterManagerImpl.reorderHoldCodeFilters");
		try {
			// lazy init connection
			init();
			invalidateCaches();
			
			return holdCodeFilterDao.reorderHoldCodeFilters(idList);
		} finally {
			dbManager.commit();
			LOGGER.debug("Commited reorderHoldCodeFilters");
			dbManager.close();
			LOGGER.debug("Closed connection");
			LOGGER.debug("End HoldCodeFilterManagerImpl.reorderHoldCodeFilters");
		}
	}
	
	@Override
	public List<HoldCodeFilter> getAllHoldCodeFilters() throws SQLException  {
		LOGGER.debug("Begin HoldCodeFilterManagerImpl.getAllHoldCodeFilters");
		try {
			// get holdcode values from cache first
			List<HoldCodeFilter> holdCodes = EhcacheFactory.getHoldCodeEhcacheWrapper().get(CommonConstants.HOLD_CODE_CACHE_KEY);
			if (holdCodes == null) {
				// lazy init connection
				init();
				holdCodes = holdCodeFilterDao.getAllHoldCodeFilters();
				// save holdcode values to cache
				EhcacheFactory.getHoldCodeEhcacheWrapper().put(CommonConstants.HOLD_CODE_CACHE_KEY, holdCodes);
			}
			return holdCodes;
		} finally {
			if (dbManager != null) {
				dbManager.close();
				LOGGER.debug("Closed connection");
			}
			LOGGER.debug("End HoldCodeFilterManagerImpl.getAllHoldCodeFilters");
		}
	}
	
	/**
	 * Invalidate cache which is using current HoldCode values.
	 */
	private void invalidateCaches() {
		// invalidate current hold code cache
		EhcacheFactory.getHoldCodeEhcacheWrapper().invalidate();
		// invalidate active hold code diagram
		EhcacheFactory.getActHldcacheWrapper().invalidate();
		// invalidate all hold duration by month 
		EhcacheFactory.getHldDurDiagramcacheWrapper().invalidate();
	}
}
